using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using System.Collections.Specialized;
using BTV.Base;
using System.Windows.Forms;

namespace BTV.Bleb
{
    public class BlebDataDownloader : BTVDataDownloader
    {

        public BlebDataDownloader(StringCollection allChannels, StringCollection channels)
            :base(allChannels, channels){}

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "ioe"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "e"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        public override void DownloadAllData()
        {
            DateTime now = DateTime.Now;
            String month = now.Month + "";
            if ( month.Length < 2 )
                month = "0" + month;
            String day = now.Day + "";
            if ( day.Length < 2 )
                day = "0" + day;
            String date = now.Year + month + day;
            String file = date + ".tgz";
            int start_days = -1;
            int end_days = 6;
            List<List<string>> channels = new List<List<string>>();
            List<string> chans = new List<string>();
            int ic = 0;
            if ( Channels != null && Channels.Count > 0 )
            {
                for ( int i = 0; i < Channels.Count; i++ )
                {
                    if ( ic == 10 )
                    {
                        ic = 0;
                        channels.Add(chans);
                        chans = new List<string>();
                    }
                    chans.Add(Channels[i]);
                    ic++;
                }
                if ( ic != 0 )
                    channels.Add(chans);
            }
            else
            {
                for ( int i = 0; i < AllChannels.Count; i++ )
                {
                    if ( ic == 10 )
                    {
                        ic = 0;
                        channels.Add(chans);
                        chans = new List<string>();
                    }
                    chans.Add(AllChannels[i]);
                    ic++;
                }
                if ( ic != 0 )
                    channels.Add(chans);
            }
            String fileformat = "tgz";
            String url = "http://www.bleb.org/tv/data/listings?days=" + start_days + ".." + end_days + "&channels="; //+ channels + "&file=" + fileformat;
            WebClient c = new WebClient();
            c.Proxy = WebRequest.DefaultWebProxy;
            c.Headers.Add("user-agent", "BTV, http://tv.blueghost.co.uk/pc/ - blueghostuk@gmail.com");
            String dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\btv\\data\\";
            String bleb_dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\btv\\data\\bleb-XML\\";
            Directory.CreateDirectory(dir);
            int lc = 0;
            foreach (List<string> l in channels)
            {
                StringBuilder d_url = new StringBuilder();
                //String d_url = url;
                d_url.Append(url);
                file = date + "_" + lc + "." + fileformat;
                int bcc = 0;
                foreach (String bc in l)
                {
                    if (bcc != 0)
                        d_url.Append(",");
                    d_url.Append(bc);
                    bcc++;
                }
                d_url.Append("&file=");
                d_url.Append(fileformat);
                if (BackgroundProcess != null)
                {
                    BackgroundWorkerPassBack bwpb = new BackgroundWorkerPassBack();
                    bwpb.TitleMessage = "Downloading TV Data From bleb.org";
                    bwpb.DetailMessage = "Getting data file from:" + d_url.ToString();
                    bwpb.IconType = ToolTipIcon.Info;
                    bwpb.IconDuration = 3000;
                    BackgroundProcess.ReportProgress(10, bwpb);
                }
                Console.WriteLine("Getting data file from:" + d_url.ToString());
                try
                {
                    c.DownloadFile(d_url.ToString(), dir + file);
                }
                catch 
                {
                    Console.WriteLine("Error 404: File Not Found");
                    if (BackgroundProcess != null)
                    {
                        BackgroundWorkerPassBack bwpb = new BackgroundWorkerPassBack();
                        bwpb.TitleMessage = "Download Incomplete";
                        bwpb.DetailMessage = "There was an error downloading the data file. Please try again later";
                        bwpb.IconType = ToolTipIcon.Error;
                        bwpb.IconDuration = 3000;
                        BackgroundProcess.ReportProgress(100, bwpb);

                    }
                    return;
                }
                lc++;
                Thread.Sleep(2000);
            }
            if (BackgroundProcess != null)
            {
                BackgroundWorkerPassBack bwpb = new BackgroundWorkerPassBack();
                bwpb.TitleMessage = "Bleb.org TV Data Download Complete";
                bwpb.DetailMessage = "All Data has been downloaded, it will now be processed";
                bwpb.IconType = ToolTipIcon.Info;
                bwpb.IconDuration = 1000;
                BackgroundProcess.ReportProgress(10, bwpb);
            }
            Console.WriteLine("Download Complete!");
             
            lc = 0;
            if (BackgroundProcess != null)
            {
                BackgroundWorkerPassBack bwpb = new BackgroundWorkerPassBack();
                bwpb.DetailMessage = "Decompressing Data Files";
                BackgroundProcess.ReportProgress(20, bwpb);
            }
            foreach (List<string> l in channels)
            {
                file = date + "_" + lc + "." + fileformat;
                Stream s = new GZipInputStream(File.OpenRead(dir + file));
                FileStream fs = File.Create(dir + Path.GetFileNameWithoutExtension(file) + ".tar");
                Console.WriteLine("Decompressing " + dir + file + " to " + Path.GetFileNameWithoutExtension(dir + file) + ".tar");
                int size = 2048;
                byte[] writeData = new byte[2048];
                while ( true )
                {
                    size = s.Read(writeData, 0, size);
                    if ( size > 0 )
                    {
                        fs.Write(writeData, 0, size);
                    }
                    else
                    {
                        break;
                    }
                }
                s.Close();
                fs.Close();
                Console.WriteLine("Decompressing " + dir + Path.GetFileNameWithoutExtension(dir + file) + ".tar");
                fs = new FileStream(dir + Path.GetFileNameWithoutExtension(file) + ".tar", FileMode.Open);
                TarArchive t = TarArchive.CreateInputTarArchive(fs);
                t.ExtractContents(dir);
                t.CloseArchive();
                fs.Close();
                Console.WriteLine("Decompressed File");
                File.Delete(dir + Path.GetFileNameWithoutExtension(file) + ".tar");
                File.Delete(dir + Path.GetFileNameWithoutExtension(file) + ".tgz");
                Console.WriteLine("Deleted Files");
                lc++;
                 
                /*rename files*/
                
                foreach ( String bc in l )
                {
                    for ( int j = -1; j <= 5; j++ )
                    {
                        DirectoryInfo sd = new DirectoryInfo(bleb_dir + j);
                        Console.WriteLine("processing files in:" + bleb_dir + j);
                        FileInfo[] finfo = sd.GetFiles();
                        DateTime pd = now.AddDays(j);
                        month = pd.Month + "";
                        if ( month.Length < 2 )
                        {
                            month = "0" + month;
                        }
                        day = pd.Day + "";
                        if ( day.Length < 2 )
                        {
                            day = "0" + day;
                        }
                        String prefix = "" + pd.Year + month + day;
                        foreach ( FileInfo f in finfo )
                        {
                            try
                            {
                                Console.WriteLine("Moving " + f.FullName + " to " + dir + prefix + f.Name);
                                File.Move(f.FullName, dir + prefix + f.Name);
                            }
                            catch
                            {
                                /*file exists so overrite*/
                                File.Delete(dir + prefix + f.Name);
                                File.Move(f.FullName, dir + prefix + f.Name);
                            }
                        }
                    }
                }
            }
            for ( int j = -1; j <= 5; j++ )
            {
                try
                {
                    Directory.Delete(bleb_dir + j);
                }
                catch { }
            }
            try
            {
                Directory.Delete(bleb_dir);
            }
            catch { }
            if (BackgroundProcess != null)
            {
                BackgroundWorkerPassBack bwpb = new BackgroundWorkerPassBack();
                bwpb.TitleMessage = "Bleb.org TV Data Update Complete";
                bwpb.DetailMessage = "All Data has been downloaded and will now be loaded";
                bwpb.IconType = ToolTipIcon.Info;
                bwpb.IconDuration = 1000;
                BackgroundProcess.ReportProgress(100, bwpb);
            }
        }
        
    }
}
